/**
    ATClab - scriptable Air Traffic Control simulations.
    Copyright (C) 2010 openatclab@gmail.com

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
**/

#ifndef __ATC_PARAM_IMPL_HDR__
#define __ATC_PARAM_IMPL_HDR__

#ifdef WIN32
	#pragma warning(disable:4786) // 'identifier' truncation
#endif


#include "param.h"

#include <map>
#include <set>
#include <string>
#include <vector>
#include <qcolor.h>
#include <qkeysequence.h>
#include "aircraft_data.h"

#define PALETTE		std::map<ControlState, Colour>
#define TOOLMAP		std::map<CanvasItem::TYPE, ToolParams>

#define TOOLSET		std::set<CanvasItem::TOOL>
#define KEYTOOLMAP	std::map<int, CanvasItem::TOOL>
#define KEYTAGMAP	std::map<int, std::string>

namespace atc{

	enum INFO_BLOCKS {
			TIME_INFO,
			SCORE_INFO,
			GOAL_INFO,
			TOOL_INFO,
			SR_GOAL_INFO,
			NORM_GOAL_INFO,
			CORRECT_DECISION_INFO,
			INCORRECT_DECISION_INFO
		};

	/*!
	 *
	 */
	struct Colour {
		Colour() : colour( Qt::black ), blink( false ) {}
		Colour( QColor c, bool b ) : colour(c), blink(b) {}

		QColor	colour;
		bool	blink;
	};

	/*!
	 * \class atc::ParamImpl
	 * \brief Experimental arameters.
	 */
	class ParamImpl : public atc::Param {
		friend class EngineImpl;
	
	public:
		ParamImpl();
		~ParamImpl();

	public: // Param interface
		void set_update_rate( unsigned int );
		
		void 
		SetAircraftAcceptanceType(AircraftAcceptanceType a_type)
		{
			m_acAcceptanceType = a_type;
		}

		void set_update_multiplier( float );
		void set_counter_format(const char *format);
		void set_hdoms(int);
		void set_vdoms(int);

		void set_conflict_colour( QColor, bool = false );
		void set_cs_colour( ControlState, QColor, bool = false );

		void set_scale_tool( const ToolParams & );
		void set_altitude_tool( const ToolParams & );
		void set_airspeed_tool( const ToolParams & );

		void set_keyed_tool( int, CanvasItem::TOOL, std::string );

		void set_srprobe( int count ) { _srprobe = count; }

		void 
		add_scoring( Score *score ) 
		{ 
			_score = score; 
		}

		void set_scale_position( GridPosition p ) { _scalePosition = p; }

		void SetConflictDeclarationScoreEnabled(bool a_enabled)
		{
			m_conflictDeclarationScoreEnabled = a_enabled;
		}

		void SetConflictDeclarationAudioEnabled(bool a_enabled)
		{
			m_conflictDeclarationAudioEnabled = a_enabled;
		}

		void SetConflictDeclarationSpeedChange(bool a_enabled)
		{
			m_conflictDeclarationSpeedChange = a_enabled;
		}

		void SetConflictDeclarationLevelChange(bool a_enabled)
		{
			m_conflictDeclarationLevelChange = a_enabled;
		}

		void add_info_block( GridPosition p ) { _infoPos = p; }
		void add_time_info()  { _infoBlk.push_back( TIME_INFO ); }
		void add_goal_info()  { _infoBlk.push_back( GOAL_INFO ); }
		void AddSelfReferentGoalInfo() { _infoBlk.push_back(SR_GOAL_INFO);}
		void AddNormativeGoalInfo() { _infoBlk.push_back(NORM_GOAL_INFO);}
		void AddCorrectDecisionsInfo() { _infoBlk.push_back(CORRECT_DECISION_INFO);}
		void AddIncorrectDecisionsInfo() { _infoBlk.push_back(INCORRECT_DECISION_INFO); }
		void add_score_info() { _infoBlk.push_back( SCORE_INFO ); }
		void add_tool_info()  { _infoBlk.push_back( TOOL_INFO ); }
	
		void set_scale_positon( GridPosition p ) { _scalePosition = p; }

		void SetGoalDisplayDetails( const std::string& a_label,
									const std::string& a_globalRef,
									const std::string& a_text)
		{
			m_goalDisplayDetails.m_label = a_label;
			m_goalDisplayDetails.m_globalRef = a_globalRef;
			m_goalDisplayDetails.m_text = a_text;
		}

		void SetCorrectDecisionsDisplayDetails(	const std::string& a_label,
												const std::string& a_globalRef,
												const std::string& a_text)
		{
			m_correctDecisionsDisplayDetails.m_label = a_label;
			m_correctDecisionsDisplayDetails.m_globalRef = a_globalRef;
			m_correctDecisionsDisplayDetails.m_text = a_text;
		}

		void SetIncorrectDecisionsDisplayDetails(	const std::string& a_label,
													const std::string& a_globalRef,
													const std::string& a_text)
		{
			m_incorrectDecisionsDisplayDetails.m_label = a_label;
			m_incorrectDecisionsDisplayDetails.m_globalRef = a_globalRef;
			m_incorrectDecisionsDisplayDetails.m_text = a_text;
		}

		void SetAircraftDeclarationText(	unsigned int a_row, 
											const std::string& a_value);

		void SetAircraftDeclarationButton(	const std::string& a_name, 
											const std::string& a_type, 
											const std::string& a_label);

	public: // accessors
		int update_rate() const { return _rate; }
		
		AircraftAcceptanceType 
		AcceptanceType() const
		{
			return m_acAcceptanceType;
		}

		bool 
		ConflictDeclarationScoreEnabled() const
		{
			return m_conflictDeclarationScoreEnabled;
		}

		bool
		ConflictDeclarationAudioEnabled() const
		{
			return m_conflictDeclarationAudioEnabled;
		}

		bool
		ConflictDeclarationSpeedChange() const
		{
			return m_conflictDeclarationSpeedChange;
		}

		bool
		ConflictDeclarationLevelChange() const
		{
			return m_conflictDeclarationLevelChange;
		}

		float update_multiplier() const { return _multiplier; }

		const std::string& counter_format()const{ return _format; }

		int hdoms()const{ return _hdoms; }
		int vdoms()const{ return _vdoms; }

		Colour conflictColour() { return _conflictColour; }
		PALETTE& palette() { return _palette; } 

		TOOLMAP       tools() { return _selectTools; }
		TOOLSET		toolSet() { return _toolSet; }
		KEYTOOLMAP keyTools() { return _keyTool; }
		KEYTAGMAP   keyTags() { return _keyTag; }

		int get_srprobe() { return _srprobe; }

		Score* get_score() { return _score; }

		GridPosition scale_position() { return _scalePosition; }

		InfoDisplayDetails GetGoalDisplayDetails() const
		{
			return m_goalDisplayDetails;
		}

		InfoDisplayDetails GetCorrectDecisionsDisplayDetails() const
		{
			return m_correctDecisionsDisplayDetails;
		}

		InfoDisplayDetails GetIncorrectDecisionsDisplayDetails() const
		{
			return m_incorrectDecisionsDisplayDetails;
		}

		AircraftDeclaration GetAircraftDeclaration() const
		{
			return m_aircraftDeclaration;
		}

	private: // members
		int				_rate;
		AircraftAcceptanceType	m_acAcceptanceType;
		float			_multiplier;
		std::string		_format;
		int				_hdoms;
		int				_vdoms;
		Colour			_conflictColour;

		PALETTE		_palette;

		TOOLMAP		_selectTools;
		TOOLSET		_toolSet;
		KEYTOOLMAP	_keyTool;
		KEYTAGMAP	_keyTag;

		// initial value for short route probe ( number of times to toggle )
		int _srprobe;

		Score *_score;

		GridPosition _scalePosition;
		GridPosition _infoPos;
		std::vector<INFO_BLOCKS> _infoBlk;
		bool				m_conflictDeclarationScoreEnabled;
		bool				m_conflictDeclarationAudioEnabled;
		bool				m_conflictDeclarationSpeedChange;
		bool				m_conflictDeclarationLevelChange;
		InfoDisplayDetails	m_goalDisplayDetails;
		InfoDisplayDetails	m_correctDecisionsDisplayDetails;
		InfoDisplayDetails	m_incorrectDecisionsDisplayDetails;
		AircraftDeclaration m_aircraftDeclaration;
	};

	
	/*!
	 *
	 */
	typedef PALETTE		Palette;

	typedef TOOLMAP		Tools;
	typedef TOOLSET		ToolSet;
	typedef KEYTOOLMAP	KeyToolMap;
	typedef KEYTAGMAP	KeyTagMap;

	typedef std::vector<INFO_BLOCKS> InfoBlockParams;
	typedef InfoBlockParams::iterator InfoBlockParamsIt;
}


#undef PALETTE
#undef TOOLMAP

#undef TOOLSET
#undef KEYTOOLMAP
#undef KEYTAGMAP


#endif
